
// @(#) $Id: AliHLTTPCTransform.cxx 61365 2013-03-09 10:39:08Z sgorbuno $
// Original: AliHLTTransform.cxx,v 1.53 2005/06/14 10:55:21 cvetan 

// Author: Anders Vestbo <mailto:vestbo@fi.uib.no>, Uli Frankenfeld <mailto:franken@fi.uib.no>, Constantin Loizides <mailto:loizides@ikf.uni-frankfurt.de>
//*-- Copyright &copy ALICE HLT Group


#include "dirent.h"

#ifdef use_aliroot
#include <AliRun.h>
#include <AliTPCParamSR.h>
#include <AliTPCPRF2D.h>
#include <AliTPCRF1D.h>
#endif
#ifdef use_root
#include <TError.h>
#include <TFile.h>
#include <TTimeStamp.h>
#include <TUnixSystem.h>
#endif

#include "AliHLTTPCLogging.h"
#include "AliHLTTPCTransform.h"

#if defined(__GNUC__) && __GNUC__ >= 3
using namespace std;
#endif

/** \class AliHLTTPCTransform 
<pre>
//_____________________________________________________________
// AliHLTTPCTransform
//
// Transformation class for ALICE TPC.
//
// Class which contains all detector specific parameters for the TPC,
// and different useful functions for coordinate transforms.
//
// The class is completely static, which means that no object needs
// to be instantiated. Function calls should then be done like, e.g.:
//
// Double_t eta = AliHLTTPCTransform::GetEta(xyz);
//
// IMPORTANT: If used as is, default detector parameters will be used,
//            and you really have to make sure that these correspond to
//            the AliROOT version you are currently working on!!
//            You should therefore always initialize the parameters by
//
//            AliHLTTPCTransform::Init(path);
// 
//            where path is a char*, giving the path to where file containing
//            the detector parameter is located. This file should be called
//            "l3transform.config", and can be created with the function MakeInitFile.
//            
//            You can also force reading the parameters from a AliTPCParam object
//            by setting the flag;
//
//            AliHLTTPCTransform::Init(path,kTRUE);
//
//            where path is a char* 
//            either providing the rootfile name containing the geometry or 
//            the path to the rootfile which should then be called alirunfile.root. 
//            Note that for both of these cases you have to
//            compile with USEPACKAGE=ALIROOT set (see level3code/Makefile.conf).
//
//            Currently, there are 4 versions of the Transformer:
//             fVersion==kValiroot: ALIROOT-head compatible
//             fVersion==kVcosmics: Cosmics data run (2003) compatible
//             fVersion==kVdefault: means no config file has been loaded
//             fVersion==kVdeprecated: dont use old (before July 2003) style of transformer
//
</pre>
* @ingroup alihlt_tpc
*/

ClassImp(AliHLTTPCTransform)

AliHLTTPCTransform::AliHLTTPCTransform()
{
}

const Double_t AliHLTTPCTransform::fgkAnodeWireSpacing = 0.25; //Taken from the TDR
const Double_t AliHLTTPCTransform::fgkBFACT = 0.0029980;       //Conversion Factor
const Double_t AliHLTTPCTransform::fgkPi  =   3.141592653589793;
const Double_t AliHLTTPCTransform::fgk2Pi = 2*3.141592653589793;
const Double_t AliHLTTPCTransform::fgkPi2 = 0.5*3.141592653589793;
const Double_t AliHLTTPCTransform::fgkToDeg = 180/3.141592653589793;

//Defined by HLT and GSI
Int_t AliHLTTPCTransform::fgNPatches = 6;
#if 0
// Old format, corresponding to IntegrTest-5 code and data
Int_t AliHLTTPCTransform::fgRows[6][2] = {{0,29},{30,62},{63,90},{91,116},{117,139},{140,158}}; 
Int_t AliHLTTPCTransform::fgNRows[6] = {30,33,28,26,23,19};
#else
// New data corresponding to simulated raw data 2004-08-20, provided by Thomas Kuhr
Int_t AliHLTTPCTransform::fgRows[6][2] = {{0,30},{30,62},{63,90},{90,116},{117,139},{139,158}}; 
Int_t AliHLTTPCTransform::fgNRows[6] = {31,33,28,27,23,20};
#endif

// The following definition is generated by MakeInitFile function
Double_t AliHLTTPCTransform::fgBField = 0.5;
Double_t AliHLTTPCTransform::fgSolenoidBField = 5;
Double_t AliHLTTPCTransform::fgBFieldFactor = 1;
Int_t AliHLTTPCTransform::fgVersion = kVdefault;
Int_t AliHLTTPCTransform::fgNTimeBins = 1024; //  = 1024; //446
Int_t AliHLTTPCTransform::fgNRowLow = 63;
Int_t AliHLTTPCTransform::fgNRowUp = 96;
Int_t AliHLTTPCTransform::fgNRowUp1 = 64;
Int_t AliHLTTPCTransform::fgNRowUp2 = 32;
Int_t AliHLTTPCTransform::fgNSectorLow = 36;
Int_t AliHLTTPCTransform::fgNSectorUp = 36;
Int_t AliHLTTPCTransform::fgNSector = 72;
Double_t AliHLTTPCTransform::fgPadPitchWidthLow = 0.4;
Double_t AliHLTTPCTransform::fgPadPitchWidthUp = 0.6;
Double_t AliHLTTPCTransform::fgZSigma = 0.2288;
Double_t AliHLTTPCTransform::fgZLength = 250.0000;
Double_t AliHLTTPCTransform::fgZWidth = AliHLTTPCTransform::fgZLength / (Double_t)AliHLTTPCTransform::fgNTimeBins ;//0.5660; // 0.2435; // 0.5660 // Width of time bins
Double_t AliHLTTPCTransform::fgZOffset = 0.6864;
Double_t AliHLTTPCTransform::fgDiffT = 0.0220;
Double_t AliHLTTPCTransform::fgDiffL = 0.0220;
Double_t AliHLTTPCTransform::fgOmegaTau = 0.1450;
Double_t AliHLTTPCTransform::fgInnerPadLength = 0.75;
Double_t AliHLTTPCTransform::fgOuter1PadLength = 1.00;
Double_t AliHLTTPCTransform::fgOuter2PadLength = 1.50;
Double_t AliHLTTPCTransform::fgInnerPRFSigma = 0.203811;
Double_t AliHLTTPCTransform::fgOuter1PRFSigma = 0.299325;
Double_t AliHLTTPCTransform::fgOuter2PRFSigma = 0.299323;
Double_t AliHLTTPCTransform::fgTimeSigma = 0.228809;
Int_t AliHLTTPCTransform::fgADCSat = 1024;
Int_t AliHLTTPCTransform::fgZeroSup = 0;
Int_t AliHLTTPCTransform::fgNSlice = 36;
Int_t AliHLTTPCTransform::fgNRow = 159;
Double_t AliHLTTPCTransform::fgNRotShift = 0.5;
Int_t AliHLTTPCTransform::fgSlice2Sector[36][2] = { { 0, 36}, 
					       { 1, 37}, 
					       { 2, 38}, 
					       { 3, 39}, 
					       { 4, 40}, 
					       { 5, 41}, 
					       { 6, 42}, 
					       { 7, 43}, 
					       { 8, 44}, 
					       { 9, 45}, 
					       {10, 46}, 
					       {11, 47}, 
					       {12, 48}, 
					       {13, 49}, 
					       {14, 50}, 
					       {15, 51}, 
					       {16, 52}, 
					       {17, 53}, 
					       {18, 54}, 
					       {19, 55}, 
					       {20, 56}, 
					       {21, 57}, 
					       {22, 58}, 
					       {23, 59}, 
					       {24, 60}, 
					       {25, 61}, 
					       {26, 62}, 
					       {27, 63}, 
					       {28, 64}, 
					       {29, 65}, 
					       {30, 66}, 
					       {31, 67}, 
					       {32, 68}, 
					       {33, 69}, 
					       {34, 70}, 
					       {35, 71}
};

Int_t AliHLTTPCTransform::fgSector2Slice[72] = { 0, 
					    1, 
					    2, 
					    3, 
					    4, 
					    5, 
					    6, 
					    7, 
					    8, 
					    9, 
					    10, 
					    11, 
					    12, 
					    13, 
					    14, 
					    15, 
					    16, 
					    17, 
					    18, 
					    19, 
					    20, 
					    21, 
					    22, 
					    23, 
					    24, 
					    25, 
					    26, 
					    27, 
					    28, 
					    29, 
					    30, 
					    31, 
					    32,
					    33, 
					    34, 
					    35, 
					    0, 
					    1, 
					    2, 
					    3, 
					    4, 
					    5, 
					    6, 
					    7, 
					    8, 
					    9, 
					    10, 
					    11, 
					    12, 
					    13, 
					    14, 
					    15, 
					    16, 
					    17, 
					    18, 
					    19, 
					    20, 
					    21, 
					    22, 
					    23, 
					    24, 
					    25, 
					    26,	
					    27, 
					    28, 
					    29, 
					    30, 
					    31, 
					    32, 
					    33, 
					    34, 
					    35 
};

Int_t AliHLTTPCTransform::fgSectorLow[72] = { 1, 
					 1, 
					 1, 
					 1, 
					 1, 
					 1, 
					 1, 
					 1, 
					 1, 
					 1, 
					 1, 
					 1, 
					 1, 
					 1, 
					 1, 
					 1, 
					 1, 
					 1, 
					 1, 
					 1, 
					 1, 
					 1, 
					 1, 
					 1, 
					 1, 
					 1, 
					 1, 
					 1, 
					 1, 
					 1, 
					 1, 
					 1, 
					 1,
					 1, 
					 1, 
					 1, 
					 0, 
					 0, 
					 0, 
					 0, 
					 0, 
					 0, 
					 0, 
					 0, 
					 0, 
					 0, 
					 0, 
					 0, 
					 0, 
					 0, 
					 0, 
					 0, 
					 0, 
					 0, 
					 0, 
					 0, 
					 0, 
					 0, 
					 0, 
					 0, 
					 0, 
					 0, 
					 0,	
					 0, 
					 0, 
					 0, 
					 0, 
					 0, 
					 0, 
					 0, 
					 0, 
					 0 
};

Double_t AliHLTTPCTransform::fgX[159] = { 85.195,
				     85.945,
				     86.695,
				     87.445,
				     88.195,
				     88.945,
				     89.695,
				     90.445,
				     91.195,
				     91.945,
				     92.695,
				     93.445,
				     94.195,
				     94.945,
				     95.695,
				     96.445,
				     97.195,
				     97.945,
				     98.695,
				     99.445,
				     100.195,
				     100.945,
				     101.695,
				     102.445,
				     103.195,
				     103.945,
				     104.695,
				     105.445,
				     106.195,
				     106.945,
				     107.695,
				     108.445,
				     109.195,
				     109.945,
				     110.695,
				     111.445,
				     112.195,
				     112.945,
				     113.695,
				     114.445,
				     115.195,
				     115.945,
				     116.695,
				     117.445,
				     118.195,
				     118.945,
				     119.695,
				     120.445,
				     121.195,
				     121.945,
				     122.695,
				     123.445,
				     124.195,
				     124.945,
				     125.695,
				     126.445,
				     127.195,
				     127.945,
				     128.695,
				     129.445,
				     130.195,
				     130.945,
				     131.695,
				     135.180,
				     136.180,
				     137.180,
				     138.180,
				     139.180,
				     140.180,
				     141.180,
				     142.180,
				     143.180,
				     144.180,
				     145.180,
				     146.180,
				     147.180,
				     148.180,
				     149.180,
				     150.180,
				     151.180,
				     152.180,
				     153.180,
				     154.180,
				     155.180,
				     156.180,
				     157.180,
				     158.180,
				     159.180,
				     160.180,
				     161.180,
				     162.180,
				     163.180,
				     164.180,
				     165.180,
				     166.180,
				     167.180,
				     168.180,
				     169.180,
				     170.180,
				     171.180,
				     172.180,
				     173.180,
				     174.180,
				     175.180,
				     176.180,
				     177.180,
				     178.180,
				     179.180,
				     180.180,
				     181.180,
				     182.180,
				     183.180,
				     184.180,
				     185.180,
				     186.180,
				     187.180,
				     188.180,
				     189.180,
				     190.180,
				     191.180,
				     192.180,
				     193.180,
				     194.180,
				     195.180,
				     196.180,
				     197.180,
				     198.180,
				     199.430,
				     200.930,
				     202.430,
				     203.930,
				     205.430,
				     206.930,
				     208.430,
				     209.930,
				     211.430,
				     212.930,
				     214.430,
				     215.930,
				     217.430,
				     218.930,
				     220.430,
				     221.930,
				     223.430,
				     224.930,
				     226.430,
				     227.930,
				     229.430,
				     230.930,
				     232.430,
				     233.930,
				     235.430,
				     236.930,
				     238.430,
				     239.930,
				     241.430,
				     242.930,
				     244.430,
				     245.930
};

#if 1
// New  number of pads changed 2006-04-15 Jochen Thaeder
// changed according to formula in AliTPCROC.cxx
// according to real Pad Distribution on build TPC
Int_t AliHLTTPCTransform::fgNPads[159] = {68,
                                     68,
                                     68,
                                     68,
                                     70,
                                     70,
                                     70,
                                     72,
                                     72,
                                     72,
                                     74,
                                     74,
                                     74,
                                     76,
                                     76,
                                     76,
                                     78,
                                     78,
                                     78,
                                     80,
                                     80,
                                     80,
                                     82,
                                     82,
                                     82,
                                     84,
                                     84,
                                     84,
                                     86,
                                     86,
                                     86,
                                     88,
                                     88,
                                     88,
                                     90,
                                     90,
                                     90,
                                     92,
                                     92,
                                     92,
                                     94,
                                     94,
                                     94,
                                     96,
                                     96,
                                     96,
                                     98,
                                     98,
                                     98,
                                     100,
                                     100,
                                     100,
                                     102,
                                     102,
                                     102,
                                     104,
                                     104,
                                     104,
                                     106,
                                     106,
                                     106,
                                     108,
                                     108,
                                     74,
                                     76,
                                     76,
                                     76,
                                     76,
                                     78,
                                     78,
                                     78,
                                     80,
                                     80,
                                     80,
                                     80,
                                     82,
                                     82,
                                     82,
                                     84,
                                     84,
                                     84,
                                     86,
                                     86,
                                     86,
                                     86,
                                     88,
                                     88,
                                     88,
                                     90,
                                     90,
                                     90,
                                     90,
                                     92,
                                     92,
                                     92,
                                     94,
                                     94,
                                     94,
                                     96,
                                     96,
                                     96,
                                     96,
                                     98,
                                     98,
                                     98,
                                     100,
                                     100,
                                     100,
                                     100,
                                     102,
                                     102,
                                     102,
                                     104,
                                     104,
                                     104,
                                     106,
                                     106,
                                     106,
                                     106,
                                     108,
                                     108,
                                     108,
                                     110,
                                     110,
                                     110,
                                     110,
                                     112,
                                     112,
                                     114,
                                     114,
                                     114,
                                     116,
                                     116,
                                     118,
                                     118,
                                     120,
                                     120,
                                     122,
                                     122,
                                     122,
                                     124,
                                     124,
                                     126,
                                     126,
                                     128,
                                     128,
                                     130,
                                     130,
                                     130,
                                     132,
                                     132,
                                     134,
                                     134,
                                     136,
                                     136,
                                     138,
                                     138,
                                     138,
                                     140
};

#else
//   OLD  number of pads changed 2006-04-15 Jochen Thaeder
Int_t AliHLTTPCTransform::fgNPads[159] = {67,
                                     67,
                                     69,
                                     69,
                                     69,
                                     71,
                                     71,
                                     71,
                                     73,
                                     73,
                                     73,
                                     75,
                                     75,
                                     75,
                                     77,
                                     77,
                                     77,
                                     79,
                                     79,
                                     79,
                                     81,
                                     81,
                                     81,
                                     83,
                                     83,
                                     83,
                                     85,
                                     85,
                                     85,
                                     87,
                                     87,
                                     87,
                                     89,
                                     89,
                                     89,
                                     91,
                                     91,
                                     91,
                                     93,
                                     93,
                                     93,
                                     95,
                                     95,
                                     95,
                                     97,
                                     97,
                                     97,
                                     99,
                                     99,
                                     99,
                                     99,
                                     101,
                                     101,
                                     101,
                                     103,
                                     103,
                                     103,
                                     105,
                                     105,
                                     105,
                                     107,
                                     107,
                                     107,
                                     73,
                                     75,
                                     75,
                                     75,
                                     75,
                                     77,
                                     77,
                                     77,
                                     79,
                                     79,
                                     79,
                                     81,
                                     81,
                                     81,
                                     81,
                                     83,
                                     83,
                                     83,
                                     85,
                                     85,
                                     85,
                                     85,
                                     87,
                                     87,
                                     87,
                                     89,
                                     89,
                                     89,
                                     91,
                                     91,
                                     91,
                                     91,
                                     93,
                                     93,
                                     93,
                                     95,
                                     95,
                                     95,
                                     95,
                                     97,
                                     97,
                                     97,
                                     99,
                                     99,
                                     99,
                                     101,
                                     101,
                                     101,
                                     101,
                                     103,
                                     103,
                                     103,
                                     105,
                                     105,
                                     105,
                                     105,
                                     107,
                                     107,
                                     107,
                                     109,
                                     109,
                                     109,
                                     111,
                                     111,
                                     111,
                                     113,
                                     113,
                                     113,
                                     115,
                                     115,
                                     117,
                                     117,
                                     119,
                                     119,
                                     121,
                                     121,
                                     121,
                                     123,
                                     123,
                                     125,
                                     125,
                                     127,
                                     127,
                                     127,
                                     129,
                                     129,
                                     131,
                                     131,
                                     133,
                                     133,
                                     135,
                                     135,
                                     135,
                                     137,
                                     137,
                                     139
};
#endif

Double_t AliHLTTPCTransform::fgCos[36] = { 0.9848077297,
				      0.8660253882,
				      0.6427876353,
				      0.3420201540,
				      0.0000000000,
				      -0.3420201540,
				      -0.6427876353,
				      -0.8660253882,
				      -0.9848077297,
				      -0.9848077297,
				      -0.8660253882,
				      -0.6427876353,
				      -0.3420201540,
				      -0.0000000000,
				      0.3420201540,
				      0.6427876353,
				      0.8660253882,
				      0.9848077297,
				      0.9848077297,
				      0.8660253882,
				      0.6427876353,
				      0.3420201540,
				      0.0000000000,
				      -0.3420201540,
				      -0.6427876353,
				      -0.8660253882,
				      -0.9848077297,
				      -0.9848077297,
				      -0.8660253882,
				      -0.6427876353,
				      -0.3420201540,
				      -0.0000000000,
				      0.3420201540,
				      0.6427876353,
				      0.8660253882,
				      0.9848077297
};

Double_t AliHLTTPCTransform::fgSin[36] = { 0.1736481786,
				      0.5000000000,
				      0.7660444379,
				      0.9396926165,
				      1.0000000000,
				      0.9396926165,
				      0.7660444379,
				      0.5000000000,
				      0.1736481786,
				      -0.1736481786,
				      -0.5000000000,
				      -0.7660444379,
				      -0.9396926165,
				      -1.0000000000,
				      -0.9396926165,
				      -0.7660444379,
				      -0.5000000000,
				      -0.1736481786,
				      0.1736481786,
				      0.5000000000,
				      0.7660444379,
				      0.9396926165,
				      1.0000000000,
				      0.9396926165,
				      0.7660444379,
				      0.5000000000,
				      0.1736481786,
				      -0.1736481786,
				      -0.5000000000,
				      -0.7660444379,
				      -0.9396926165,
				      -1.0000000000,
				      -0.9396926165,
				      -0.7660444379,
				      -0.5000000000,
				      -0.1736481786
};

Int_t AliHLTTPCTransform::GetNPads(Int_t row)
{
  //get number of pads per row
  if(row < 0 || row >= fgNRow)
    {
      LOG(AliHLTTPCLog::kError,"AliHLTTPCTransform::GetNPads","Row")
	<<AliHLTTPCLog::kDec<<"Wrong row "<<row<<ENDLOG;
      return 0;
    }

  return fgNPads[row];
}

Int_t AliHLTTPCTransform::GetNumberOfPatches() {
  return fgNPatches;
}

Int_t AliHLTTPCTransform::GetFirstRow(Int_t patch)
{
  //get first row per patch

  if(patch==-1)
    return 0;
  else if(patch < -1 || patch >= 6)
    {
      LOG(AliHLTTPCLog::kError,"AliHLTTPCTransform::GetFirstRow","Patch")
	<<AliHLTTPCLog::kDec<<"Wrong patch "<<patch<<ENDLOG;
      return 0;
    }
  else
    return fgRows[patch][0];
}

Int_t AliHLTTPCTransform::GetLastRow(Int_t patch)
{
  //get last row per patch
  if(patch==-1)
    return fgRows[5][1];
  else if(patch < -1 || patch >= 6)
    {
      LOG(AliHLTTPCLog::kError,"AliHLTTPCTransform::GetLastRow","Patch")
	<<AliHLTTPCLog::kDec<<"Wrong patch "<<patch<<ENDLOG;
      return 0;
    }
  else
    return fgRows[patch][1];
}

Int_t AliHLTTPCTransform::GetFirstRowOnDDL(Int_t patch)
{
  //get first row per patch

  if(patch==-1)
    return 0;
  else if(patch < -1 || patch >= 6)
    {
      LOG(AliHLTTPCLog::kError,"AliHLTTPCTransform::GetFirstRow","Patch")
	<<AliHLTTPCLog::kDec<<"Wrong patch "<<patch<<ENDLOG;
      return 0;
    }
  else
    {
      if(patch==1) return fgRows[patch][0]+1;
      return fgRows[patch][0];
    }
}

Int_t AliHLTTPCTransform::GetLastRowOnDDL(Int_t patch)
{
  //get last row per patch
  if(patch==-1)
    return fgRows[5][1];
  else if(patch < -1 || patch >= 6)
    {
      LOG(AliHLTTPCLog::kError,"AliHLTTPCTransform::GetLastRow","Patch")
	<<AliHLTTPCLog::kDec<<"Wrong patch "<<patch<<ENDLOG;
      return 0;
    }
  else
    {
      if(patch==2 || patch==4) return fgRows[patch][1]-1;
      return fgRows[patch][1];
    }
}

Int_t AliHLTTPCTransform::GetNRows(Int_t patch)
{
  //get number of rows per patch
  if(patch==-1)
    return fgNRow;
  else if(patch < -1 || patch >= 6)
    {
      LOG(AliHLTTPCLog::kError,"AliHLTTPCTransform::GetNRows","Patch")
	<<AliHLTTPCLog::kDec<<"Wrong patch "<<patch<<ENDLOG;
      return 0;
    }
  else
    return fgNRows[patch];
}

Int_t AliHLTTPCTransform::GetPadRow(Float_t xvalue)
{
  //Find the padrow number corresponding to cartesian _local_ x value
  if(xvalue < 0 || xvalue > 250)
    {
      LOG(AliHLTTPCLog::kError,"AliHLTTPCTransform::GetPadRow","X-value")
	<<AliHLTTPCLog::kDec<<"Suspicious x-value, make sure it is in local coordinate! "
	<<xvalue<<ENDLOG;
      return -1;
    }
  
  Int_t x = (Int_t)rint(xvalue*10);
  if(x < (Int_t)rint(fgX[1]*10))
    return 0;
  else if(x > (Int_t)rint(fgX[fgNRow-2]*10))
    return fgNRow-1;
  else
    {
      Int_t padrow=1; //Of course, a more clever algorithm could help here
      while(padrow < fgNRow-2)
	{
	  if(x > (Int_t)rint(fgX[padrow-1]*10) && x < (Int_t)rint(fgX[padrow+1]*10))
	    break;
	  padrow++;
	}
      return padrow;
    }
}

Int_t AliHLTTPCTransform::GetPatch(Int_t padrow)
{
  //get patch for padrow
  if(padrow < 0 || padrow >= fgNRow)
    {
      LOG(AliHLTTPCLog::kError,"AliHLTTPCTransform::GetPatch","Padrow")
	<<AliHLTTPCLog::kDec<<"Wrong padrow "<<padrow<<ENDLOG;
      return -2;
    }
  Int_t patch=0;
  while(patch < fgNPatches)
    {
      if(padrow >= fgRows[patch][0] && padrow <= fgRows[patch][1])
	break;
      patch++;
    }
  return patch;
}

Double_t AliHLTTPCTransform::GetPadLength(Int_t padrow)
{
  //get pad length for padrow
  if(padrow >= fgNRow){
      LOG(AliHLTTPCLog::kError,"AliHLTTPCTransform::GetPadLength","Padrow")
	<<AliHLTTPCLog::kDec<<"Wrong padrow "<<padrow<<ENDLOG;
      return 0;
    }

  if(padrow < fgNRowLow)
    return fgInnerPadLength;
  if(padrow >= fgNRowLow && padrow < fgNRowLow + fgNRowUp1 - 1)
    return fgOuter1PadLength;
  if(padrow >= fgNRowLow + fgNRowUp1 - 1)
    return fgOuter2PadLength;

  //should never happen
  LOG(AliHLTTPCLog::kError,"AliHLTTPCTransform::GetPadLength","Padrow")
    <<AliHLTTPCLog::kDec<<"Wrong padrow "<<padrow<<ENDLOG;
  return -1.0; 
}

Double_t AliHLTTPCTransform::GetPadPitchWidth(Int_t patch)
{
  //get pad patch width for patch
  if(patch < 0 || patch > fgNPatches)
    {
      LOG(AliHLTTPCLog::kError,"AliHLTTPCTransform::GetPadPitchWidth","patct")
	<<AliHLTTPCLog::kDec<<"Wrong patch "<<patch<<ENDLOG;
      return -1;
    }
  return patch < 2 ? fgPadPitchWidthLow : fgPadPitchWidthUp;  
}

Double_t AliHLTTPCTransform::GetParSigmaY2(Int_t padrow,Float_t z,Float_t angle)
{
  //Calculate the expected transverse cluster width as a function of 
  //drift distance and crossing angle.
  //z = local z-coordinate of cluster
  //angle = track crossing angle with normal to padrow plane
  //return value = sigma^2 (cartesian coordinates)

  Double_t drift;
  if(z > 0)
    drift = fgZLength - z;
  else
    drift = fgZLength + z;
  
  Double_t t1 = GetPRFSigma(padrow)*GetPRFSigma(padrow);
  Double_t t2 = fgDiffT*fgDiffT*drift;
  Double_t t3 = GetPadLength(padrow)*GetPadLength(padrow)*tan(angle)*tan(angle)/12;
  Double_t t4 = fgkAnodeWireSpacing*fgkAnodeWireSpacing*(tan(angle) - fgOmegaTau)*(tan(angle) - fgOmegaTau)/12;

  return (t1 + t2 + t3 + t4);
}

Double_t AliHLTTPCTransform::GetParSigmaZ2(Int_t padrow,Float_t z,Float_t tgl)
{
  //Calculate the expected longitudinal cluster width as a function of 
  //drift distance and track crossing angle.
  //z = local z-coordinate of cluster
  //tgl = tan(dipangle) 
  //return value = sigma^2 (cartesian coordinates)

  Double_t drift;
  if(z > 0)
    drift = AliHLTTPCTransform::GetZLength()-0.275 - z;
  else
    drift = AliHLTTPCTransform::GetZLength()-0.302 + z;
  
  Double_t t1 = fgZSigma*fgZSigma;
  Double_t t2 = fgDiffL*fgDiffL*drift;
  Double_t t3 = GetPadLength(padrow)*GetPadLength(padrow)*tgl*tgl/12;
  
  return (t1 + t2 + t3);
}

Double_t AliHLTTPCTransform::GetPRFSigma(Int_t padrow)
{
  //get sigma of pad response function for padrow

  if(padrow >= fgNRow){
    LOG(AliHLTTPCLog::kError,"AliHLTTPCTransform::GetPRFSigma","Padrow")
      <<AliHLTTPCLog::kDec<<"Wrong padrow "<<padrow<<ENDLOG;
    return 0;
  }
  if(padrow < fgNRowLow)
    return fgInnerPRFSigma;
  if(padrow >= fgNRowLow && padrow < fgNRowLow + fgNRowUp1 - 1)
    return fgOuter1PRFSigma;
  if(padrow >= fgNRowLow + fgNRowUp1 - 1)
    return fgOuter2PRFSigma;

  //should never happen
  LOG(AliHLTTPCLog::kError,"AliHLTTPCTransform::GetPRFSigma","Padrow")
    <<AliHLTTPCLog::kDec<<"Wrong padrow "<<padrow<<ENDLOG;
  return -1.; 
}

Double_t AliHLTTPCTransform::GetEta(Float_t *xyz)
{
  //get eta
  Double_t r3 = sqrt(xyz[0]*xyz[0]+xyz[1]*xyz[1]+xyz[2]*xyz[2]);
  Double_t eta = 0.5 * log((r3+xyz[2])/(r3-xyz[2]));
  return eta;
}

void AliHLTTPCTransform::XYZtoRPhiEta(Float_t *rpe, Float_t *xyz)
{
  //transform xyz into rpe
  rpe[0] = sqrt(xyz[0]*xyz[0]+xyz[1]*xyz[1]+xyz[2]*xyz[2]);
  rpe[1] = atan2(xyz[1],xyz[0]);
  rpe[2] = 0.5 * log((rpe[0]+xyz[2])/(rpe[0]-xyz[2]));
}

Double_t AliHLTTPCTransform::GetEta(Int_t slice,Int_t padrow,Int_t pad,Int_t time)
{
  //get eta
  Float_t xyz[3];
  Int_t sector,row;
  Slice2Sector(slice,padrow,sector,row);
  Raw2Local(xyz,sector,row,pad,time);
  
  return GetEta(xyz);
}

Double_t AliHLTTPCTransform::GetPhi(Float_t *xyz)
{
  //get phi
  Double_t phi = atan2(xyz[1],xyz[0]);
  return phi;
}

Bool_t AliHLTTPCTransform::Slice2Sector(Int_t slice, Int_t slicerow, Int_t & sector, Int_t &row)
{
  //slice no to sector number
  //row no to local sector row no
  if(slicerow<0&&slicerow>=fgNRow){
    LOG(AliHLTTPCLog::kError,"AliHLTTPCTransform::Slice2Sector","Slicerow")
      <<AliHLTTPCLog::kDec<<"Wrong slicerow "<<slicerow<<ENDLOG;
    return kFALSE;
  }
  if(slice<0||slice>=fgNSlice){
    LOG(AliHLTTPCLog::kError,"AliHLTTPCTransform::Slice2Sector","Slice")
      <<AliHLTTPCLog::kDec<<"Wrong slice "<<slice<<ENDLOG;
    return kFALSE;
  }

  if(slicerow<fgNRowLow){
    sector = fgSlice2Sector[slice][0];
    row    = slicerow;
  }
  else {
    sector = fgSlice2Sector[slice][1];
    row    = slicerow-fgNRowLow;
  }

  return kTRUE;
}

Bool_t AliHLTTPCTransform::Sector2Slice(Int_t & slice, Int_t  sector)
{
  //sector to slice
  if(sector<0||sector>=fgNSector){
    LOG(AliHLTTPCLog::kError,"AliHLTTPCTransform::Sector2Slice","Sector")
      <<AliHLTTPCLog::kDec<<"Wrong sector "<<sector<<ENDLOG;
    return kFALSE;
  }

  slice=fgSector2Slice[sector];

  return kTRUE;
}

Bool_t AliHLTTPCTransform::Sector2Slice(Int_t & slice, Int_t & slicerow, Int_t sector, Int_t row)
{
  //sector to slice
  if(sector<0 || sector>=fgNSector){
    LOG(AliHLTTPCLog::kError,"AliHLTTPCTransform::Sector2Slice","Sector")
      <<AliHLTTPCLog::kDec<<"Wrong sector "<<sector<<ENDLOG;
    return kFALSE;
  }
  if(row<0){
    LOG(AliHLTTPCLog::kError,"AliHLTTPCTransform::Sector2Slice","Row")
      <<AliHLTTPCLog::kDec<<"Wrong row "<<row<<ENDLOG;
    return kFALSE;
  }

  if(fgSectorLow[sector]){
    if(row>=fgNRowLow){
      LOG(AliHLTTPCLog::kError,"AliHLTTPCTransform::Sector2Slice","Row")
	<<AliHLTTPCLog::kDec<<"Wrong row "<<row<<ENDLOG;
      return kFALSE;
    }
    slice = fgSector2Slice[sector];
    slicerow = row;
  }
  else{
    if(row>=fgNRowUp){
      LOG(AliHLTTPCLog::kError,"AliHLTTPCTransform::Sector2Slice","Row")
	<<AliHLTTPCLog::kDec<<"Wrong row "<<row<<ENDLOG;
      return kFALSE;
    }
    slice = fgSector2Slice[sector];
    slicerow = row + fgNRowLow;
  }

  return kTRUE;
}

Double_t AliHLTTPCTransform::GetMaxY(Int_t slicerow)
{
  //get maximum y value (for slice 0)
  if (slicerow>=fgNRow) {
    LOG(AliHLTTPCLog::kError,"AliHLTTPCTransform::GetMaxY","Slicerow")
      <<AliHLTTPCLog::kDec<<"slicerow out of range"<<slicerow<<ENDLOG;
  }
 if(slicerow < fgNRowLow)
     return fgPadPitchWidthLow*fgNPads[slicerow]/2; 
 
 else
     return fgPadPitchWidthUp*fgNPads[slicerow]/2;

}

Double_t AliHLTTPCTransform::Row2X(Int_t slicerow)
{
  //slicerow to X value (slice 0)
  if(slicerow<0||slicerow>=fgNRow){
    LOG(AliHLTTPCLog::kError,"AliHLTTPCTransform::Row2X","Slicerow")
      <<AliHLTTPCLog::kDec<<"Wrong slicerow "<<slicerow<<ENDLOG;
    return 0;
  }
  return fgX[slicerow];
}

Double_t AliHLTTPCTransform::GetZFast(Int_t slice, Int_t time, Float_t vertex)
{
  //get z value
  Double_t z=fgZWidth*time-fgZOffset;
  if(slice < 18)
    z=fgZLength-z-vertex;
  else
    z=z-fgZLength-vertex;
  return z;
}

void AliHLTTPCTransform::Local2Global(Float_t *xyz,Int_t slice)
{
  //Transformation to global coordinate system
  Float_t x0 = xyz[0];
  Float_t y0 = xyz[1];

  xyz[0]=x0*fgCos[slice]-y0*fgSin[slice];
  xyz[1]=x0*fgSin[slice]+y0*fgCos[slice];
  //xyz[2]=xyz[2];//global z=local z
}

void AliHLTTPCTransform::Local2GlobalAngle(Float_t *angle,Int_t slice)
{
  //get angle global
  angle[0] = fmod(angle[0]+(slice+fgNRotShift)*(2*fgkPi/18),2*fgkPi);
}

void AliHLTTPCTransform::Global2LocalAngle(Float_t *angle,Int_t slice)
{
  //get angle local
  angle[0] = angle[0]-(slice+fgNRotShift)*(2*fgkPi/18);
  if(angle[0]<0) angle[0]+=2*fgkPi;
}

void AliHLTTPCTransform::Raw2Local(Float_t *xyz,Int_t sector,Int_t row,Float_t pad,Float_t time)
{
  //Transformation from rawdata to local coordinate system
  
  Int_t slice,slicerow;
  if (Sector2Slice(slice, slicerow, sector, row)==kFALSE) return;

  //X-Value
  xyz[0]=Row2X(slicerow); 

  //Y-Value
  if (slicerow>=fgNRow) {
    LOG(AliHLTTPCLog::kError,"AliHLTTPCTransform::GetMaxY","Slicerow")
      <<AliHLTTPCLog::kDec<<"slicerow out of range"<<slicerow<<ENDLOG;
    return;
  }
  Int_t npads= fgNPads[slicerow];

  if(fgSectorLow[sector])
    xyz[1]=(pad-0.5*(npads))*fgPadPitchWidthLow;
  else
    xyz[1]=(pad-0.5*(npads))*fgPadPitchWidthUp;

  //Z-Value (remember PULSA Delay)
  if(slice < 18)
    xyz[2]=GetZLength()-GetZWidth()*time+GetZOffset();
  else
    xyz[2]=GetZWidth()*time-GetZOffset()-GetZLength();
}

void AliHLTTPCTransform::Raw2Local(Float_t *xyz,Int_t sector,Int_t row,Int_t pad,Int_t time)
{
  //Transformation from rawdata to local coordinate system
  
  Int_t slice,slicerow;
  Sector2Slice(slice, slicerow, sector, row);  

  //X-Value
  xyz[0]=Row2X(slicerow); 

  //Y-Value
  Int_t npads= fgNPads[slicerow];

  if(fgSectorLow[sector])
    xyz[1]=(pad-0.5*(npads-1))*fgPadPitchWidthLow;
  else
    xyz[1]=(pad-0.5*(npads-1))*fgPadPitchWidthUp;

  //Z-Value (remember PULSA Delay)
  if(slice < 18)
    xyz[2]=GetZLength()-GetZWidth()*time+GetZOffset();
  else
    xyz[2]=GetZWidth()*time-GetZOffset()-GetZLength();
}

void AliHLTTPCTransform::RawHLT2Local(Float_t *xyz,Int_t slice,
                               Int_t slicerow,Float_t pad,Float_t time)
{
  //Transformation from HLT rawdata to local coordinate system
  
  //X-Value
  xyz[0]=Row2X(slicerow); 

  //Y-Value
  Int_t npads= fgNPads[slicerow];
  if(slicerow<fgNRowLow)
    xyz[1]=(pad-0.5*(npads-1))*fgPadPitchWidthLow;
  else
    xyz[1]=(pad-0.5*(npads-1))*fgPadPitchWidthUp;

  //Z-Value
  if(slice < 18)
    xyz[2]=GetZLength()-GetZWidth()*time+GetZOffset();
  else
    xyz[2]=GetZWidth()*time-GetZOffset()-GetZLength();
}

void AliHLTTPCTransform::RawHLT2Local(Float_t *xyz,Int_t slice,
                               Int_t slicerow,Int_t pad,Int_t time)
{
  //Transformation from HLT rawdata to local coordinate system
  
  //X-Value
  xyz[0]=Row2X(slicerow); 

  //Y-Value
  Int_t npads= fgNPads[slicerow];
  if(slicerow<fgNRowLow)
    xyz[1]=(pad-0.5*(npads-1))*fgPadPitchWidthLow;
  else
    xyz[1]=(pad-0.5*(npads-1))*fgPadPitchWidthUp;

  //Z-Value
  if(slice < 18)
    xyz[2]=GetZLength()-GetZWidth()*time+GetZOffset();
  else
    xyz[2]=GetZWidth()*time-GetZOffset()-GetZLength();
}

void AliHLTTPCTransform::Local2Global(Float_t *xyz,Int_t sector,Int_t row)
{
  //Transformation to global coordinate system
  Int_t slice,slicerow;
  Sector2Slice(slice, slicerow, sector, row);  
  Float_t r=Row2X(slicerow); //have to get x value first
                             
  xyz[0]=r*fgCos[slice]-xyz[1]*fgSin[slice];
  xyz[1]=r*fgSin[slice]+xyz[1]*fgCos[slice];
  //xyz[2]=xyz[2];//global z=local z
}

void AliHLTTPCTransform::LocHLT2Global(Float_t *xyz,Int_t slice,Int_t slicerow)
{
  //Transformation from HLT to global coordinate system
  Float_t r=Row2X(slicerow); //have to get x value first
                             
  xyz[0]=r*fgCos[slice]-xyz[1]*fgSin[slice];
  xyz[1]=r*fgSin[slice]+xyz[1]*fgCos[slice];
  //xyz[2]=xyz[2];//global z=local z
}

void AliHLTTPCTransform::Global2Local(Float_t *xyz,Int_t sector)
{ //check code
  Int_t slice;
  Sector2Slice(slice, sector);  

  Float_t x1 =  xyz[0]*fgCos[slice] + xyz[1]*fgSin[slice];
  Float_t y1 = -xyz[0]*fgSin[slice] + xyz[1]*fgCos[slice];
  xyz[0] = x1;
  xyz[1] = y1;
}

void AliHLTTPCTransform::Global2LocHLT(Float_t *xyz,Int_t slice)
{
  Float_t x1 =  xyz[0]*fgCos[slice] + xyz[1]*fgSin[slice];
  Float_t y1 = -xyz[0]*fgSin[slice] + xyz[1]*fgCos[slice];
  xyz[0] = x1;
  xyz[1] = y1;
}

void AliHLTTPCTransform::Raw2Global(Float_t *xyz,Int_t sector,Int_t row,Float_t pad,Float_t time)
{
  //Transformation from raw to global coordinates
 
  Raw2Local(xyz,sector,row,pad,time);
  Local2Global(xyz,sector,row);
}

void AliHLTTPCTransform::Raw2Global(Float_t *xyz,Int_t sector,Int_t row,Int_t pad,Int_t time)
{
  //Transformation from raw to global coordinates
 
  Raw2Local(xyz,sector,row,pad,time);
  Local2Global(xyz,sector,row);
}

void AliHLTTPCTransform::RawHLT2Global(Float_t *xyz,Int_t slice,
                                   Int_t slicerow,Float_t pad,Float_t time)
{
  //Transformation from raw to global coordinates
 
  RawHLT2Local(xyz,slice,slicerow,pad,time);
  LocHLT2Global(xyz,slice,slicerow);
}

void AliHLTTPCTransform::RawHLT2Global(Float_t *xyz,Int_t slice,
                                   Int_t slicerow,Int_t pad,Int_t time)
{
  //Transformation from raw to global coordinates
 
  RawHLT2Local(xyz,slice,slicerow,pad,time);
  LocHLT2Global(xyz,slice,slicerow);
}

void AliHLTTPCTransform::Local2Raw(Float_t *xyz,Int_t sector,Int_t row)
{
  //Transformation from local coordinates to raw

  Int_t slice,slicerow;
  Sector2Slice(slice, slicerow, sector, row);  
   
  xyz[0]=slicerow;

  if(fgSectorLow[sector])
    xyz[1]=xyz[1]/fgPadPitchWidthLow+0.5*(fgNPads[slicerow]-1);
  else
    xyz[1]=xyz[1]/fgPadPitchWidthUp+0.5*(fgNPads[slicerow]-1);

  if(slice < 18)
    xyz[2]=(GetZLength()-xyz[2]+GetZOffset())/GetZWidth();
  else
    xyz[2]=(GetZLength()+xyz[2]+GetZOffset())/GetZWidth();

  if( xyz[2]<0 ) xyz[2]=0; // protection for negative timebin values
}

void AliHLTTPCTransform::LocHLT2Raw(Float_t *xyz,Int_t slice,Int_t slicerow)
{
  //Transformation from local coordinates to raw

  xyz[0]=slicerow;

  int sign=slice<18?1:-1;
  if(slicerow<fgNRowLow)
    xyz[1]=sign*xyz[1]/fgPadPitchWidthLow+0.5*(fgNPads[slicerow]);
  else
    xyz[1]=sign*xyz[1]/fgPadPitchWidthUp+0.5*(fgNPads[slicerow]);

  if(slice < 18)
    xyz[2]=(GetZLength()-xyz[2]+GetZOffset())/GetZWidth();
  else
    xyz[2]=(GetZLength()+xyz[2]+GetZOffset())/GetZWidth();
}

void AliHLTTPCTransform::Global2Raw(Float_t *xyz,Int_t sector,Int_t row)
{
  //Transformation from global coordinates to raw. 

  Global2Local(xyz,sector);
  Local2Raw(xyz,sector,row);
}

void AliHLTTPCTransform::Global2HLT(Float_t *xyz,Int_t slice,Int_t slicerow)
{
  //Transformation from global coordinates to raw. 

  Global2LocHLT(xyz,slice);
  LocHLT2Raw(xyz,slice,slicerow);
}

void AliHLTTPCTransform::PrintCompileOptions()
{
  //print compile options
#if defined(__GNUC__)
  cout << "Compiler (g++) version used: " << __GNUC__ << endl;
#endif

#ifdef no_root
  cout << "STANDALONE version: -Dno_root was given." << endl;
#else
  const Char_t *roottest="$ROOTSYS/bin/root -n -b -q  | grep Version | cut -b 17-25 | cut -d\" \" -f1";
#ifdef use_aliroot
#ifdef use_cvs
  const Char_t *aliroottest="if test -n \"`cd $ALICE_ROOT/STEER/ && cvs stat AliRun.cxx | grep \"Sticky Tag\" | grep none`\"; then echo HEAD; else cd $ALICE_ROOT/STEER/ && cvs stat AliRun.cxx | grep \"Sticky Tag\" | cut -b 18- | cut -d\" \" -f1; fi";
#else
  const Char_t *aliroottest="Unknown";
#endif
  cout << "ALIROOT version: -Duse_aliroot and -Duse_root was given." << endl;
  cout << "Root Version: " << ROOTVERSION << " found " << flush;
  gSystem->Exec(roottest);

  cout << "AliRoot Version: " << ALIROOTVERSION << " found " << flush;
  gSystem->Exec(aliroottest);
#else
  cout << "ROOT version: -Duse_root was given." << endl;
  cout << "Root Version: " << ROOTVERSION << " found " << flush;
  gSystem->Exec(roottest);
#endif
#endif

#ifdef do_mc
  cout << "Using Monte Carlo Info: -Ddo_mc was given." << endl;
#else
  cout << "NOT using Monte Carlo Info: -Ddo_mc was not given." << endl;
#endif

#ifdef INCLUDE_TPC_HOUGH
  cout << "Including support for TPC Hough transformations." << endl;
#ifdef ROWHOUGHPARAMS
  cout << "Using extended AliHLTTPCTrackSegmentData: -DROWHOUGHPARAMS was given." << endl;
#else
  cout << "NOT using extended AliHLTTPCTrackSegmentData: -DROWHOUGHPARAMS was not given." << endl;
#endif
#else
  cout << "NOT including any support for TPC Hough transformations." << endl;
#endif // INCLUDE_TPC_HOUGH

}
